/*
 * @Author: 来自火星的码农 15122322+heyzhi@user.noreply.gitee.com
 * @Date: 2025-08-07 17:34:45
 * @LastEditors: 来自火星的码农 15122322+heyzhi@user.noreply.gitee.com
 * @LastEditTime: 2025-09-19 21:04:52
 * @FilePath: /server/workspace/src/base/timer.cc
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
#include"timer.h"
#include "base/Log.h"
#include "mutex.h"
#include"util.h"
namespace Yizhi{

    bool Timer::Comparator::operator()(const Timer::ptr& lhs,const Timer::ptr& rhs) const{
        if(!lhs&&!rhs){
            return false;
        }
        if(!lhs){
            return true;
        }
        if(!rhs){ 
            return false;
        }
        if(lhs->m_next<rhs->m_next){
            return true;
        }
        if(rhs->m_next<lhs->m_next){
            return false;
        }
        return lhs.get()< rhs.get();
 
    }
    Timer::Timer(uint64_t ms,bool recurring,TimerManager *Manager,CallbackType cb)
    :m_ms(ms)
    ,m_recurring(recurring)
    ,m_cb(cb)
    ,m_manager(Manager)
    {
        auto now=Yizhi::GetcurrentMs();
        m_next=now+m_ms;
    }

    Timer::Timer(uint64_t next){
        m_next=next;
    }

    /// @brief 当回调函数存在时，置空并从set中删除，否则do nothing
    /// @return 
    bool Timer::cancel(){
        RWMutexType::WriteLock wlock(m_manager->m_mutex);
        if(m_cb){
            m_cb=nullptr;
            auto it=m_manager->m_timers.find(shared_from_this());
            m_manager->m_timers.erase(it);
            return true;
        }
        return false;
    }

    /// @brief 当回调函数存在时，先取出来并删除，然后更新
    /// @return 
    bool Timer::refush(){
        RWMutexType::WriteLock wlock(m_manager->m_mutex);
        if(!m_cb){
            return false;
        }
        if(m_manager->m_timers.find(shared_from_this())==m_manager->m_timers.end()){
            return false;
        }
        auto val=shared_from_this();
        auto self=m_manager->m_timers.find(val);
        m_manager->m_timers.erase(self);
        m_next=Yizhi::GetcurrentMs()+m_ms;
        m_manager->addTimer(val,wlock);
        return true;
    };

    /// @brief 重置执行时间
    /// @param ms 要修改成的执行时间 
    /// @param fromnow 是否从当前开始计时
    /// @return 
    bool Timer::reset(uint64_t ms,bool fromnow){

      
        
        RWMutexType::WriteLock wlock(m_manager->m_mutex);
        if(m_cb==nullptr){
            return false;
        }
        auto val=shared_from_this();
        auto it=m_manager->m_timers.find(val);
        if(it==m_manager->m_timers.end()){
            return false;
        }
        if(m_ms==ms&&!fromnow){
            return true;
        }

        m_manager->m_timers.erase(it);
       
        uint64_t start=0;
        if(fromnow){
            start=Yizhi::GetcurrentMs();

        }
        else{
            start=m_next-m_ms;
        }
        m_ms=ms;

        m_next=start+m_ms;
     
        m_manager->addTimer(val,wlock);
        return true;

    }


    TimerManager::TimerManager(){

    }
    TimerManager::~TimerManager(){
        
    }

    Timer::ptr TimerManager::addTimer(uint64_t ms,CallbackType cb,bool recurring){
       
        Timer::ptr timer(new Timer(ms,recurring,this,cb));
        RWMutexType::WriteLock wlock(m_mutex);
        addTimer(timer,wlock);
        return timer;
    }



    void TimerManager::addTimer(Timer::ptr val,RWMutexType::WriteLock& wlock){
        auto it=m_timers.insert(val).first;
        bool at_front=(it==m_timers.begin())&&!m_tickle;
        if(at_front){
          m_tickle=true;
          wlock.unlock();
          onTimerInsertFront();
        }
        else{
            wlock.unlock();
        }
    }


    static void onTimer(std::function<void()> cb,std::weak_ptr<void> weak_cond){
        auto tmp=weak_cond.lock();
        if(tmp){
            cb();
        }
    }


    Timer::ptr TimerManager::addCondtionTimer(uint64_t ms,CallbackType cb, 
                            std::weak_ptr<void> con_ptr,bool recurring){
  
            
        return addTimer(ms,std::bind(&onTimer,cb,con_ptr),recurring);
    }

    uint64_t TimerManager::GetNextTimer(){
        RWMutexType::ReadLock rlock(m_mutex);
        m_tickle=false;
        if(m_timers.empty()){
            return ~0ull;
        }
      
        const Timer::ptr& next=*m_timers.begin();
        uint64_t now_ms=Yizhi::GetcurrentMs();


        //已经超时
        if(now_ms>=next->m_next){
            return 0;
        }

        //未超时，返回剩余时间
        return next->m_next-now_ms;
    }


    void TimerManager::listExpiredCb(std::vector<std::function<void()>> &cbs){
        {
            
            uint64_t now_ms=Yizhi::GetcurrentMs();
            std::vector<Timer::ptr>expired;
            {
              RWMutexType::ReadLock rlock(m_mutex);
              if(m_timers.empty()){
                return ;
              }
            }

            RWMutexType::WriteLock wlock(m_mutex);
            Timer::ptr now_timer(new Timer(now_ms));
            auto it=m_timers.lower_bound(now_timer);
            while(it!=m_timers.end()&&(*it)->m_next==now_ms){
                it++;
            }

            expired.insert(expired.begin(),m_timers.begin(),it);
            m_timers.erase(m_timers.begin(),it);
            cbs.reserve(expired.size());
            for(auto timer:expired){
                cbs.push_back(timer->m_cb);
                if(timer->m_recurring){
                    timer->m_next=now_ms+timer->m_ms;
                    m_timers.insert(timer);
                }
                else{
                    timer->m_cb=nullptr;
                }
            }
            
        }
    }
    
    bool TimerManager::hasNext(){
        RWMutexType::ReadLock rlock(m_mutex);
        return m_timers.empty();
    }
  
    
    
}
